package model

import (
	"admin/contrib/conn"
	ryrpc "admin/rpc"
	"common/helper"
	"context"
	"fmt"
	"github.com/bytedance/gopkg/util/xxhash3"
	"strings"
	"time"
	"unicode/utf8"

	"github.com/ip2location/ip2location-go/v9"

	g "github.com/doug-martin/goqu/v9"
	_ "github.com/doug-martin/goqu/v9/dialect/mysql"
	"github.com/go-redis/redis/v8"
	"github.com/jmoiron/sqlx"
	"github.com/meilisearch/meilisearch-go"
	"github.com/spaolacci/murmur3"
)

type aws_t struct {
	Bucket          string `toml:"bucket"`
	AccessKeyID     string `toml:"accessKeyID"`
	SecretAccessKey string `toml:"secretAccessKey"`
}

type TgPay struct {
	AppKey string `toml:"appKey"`
}

type MetaTable struct {
	IpDB          *ip2location.DB
	MerchantS3    aws_t
	MerchantDB    MerchantDB
	MasterDB      *sqlx.DB
	SlaveDB       *sqlx.DB
	MerchantBean  *conn.Connection
	MerchantRedis *redis.Client
	IsDev         bool
	Program       string
	RPCPath       string
	Meili         *meilisearch.Client
	GcsDomain     string
	Callback      string
	WebUrl        string
	BannerUrl     string
	TgPay         TgPay
	RedisDBIndex  int
}

var (
	meta    *MetaTable
	ctx     = context.Background()
	dialect = g.Dialect("mysql")
	loc     *time.Location

	colsMemberVip             = helper.EnumFields(MemberVip{})
	colsWhiteList             = helper.EnumFields(TblWhitelist{})
	colsBanner                = helper.EnumFields(TblBanner{})
	colsMember                = helper.EnumFields(ryrpc.TblMemberBase{})
	colsDeposit               = helper.EnumFields(tblDeposit{})
	colsAdmin                 = helper.EnumFields(Admin{})
	colsGroup                 = helper.EnumFields(Group{})
	colsPromoSignConfig       = helper.EnumFields(PromoSignConfig{})
	colsPromoSignRecord       = helper.EnumFields(PromoSignRecord{})
	colsPromoDepositConfig    = helper.EnumFields(PromoDepositConfig{})
	colsPromoSignRewardRecord = helper.EnumFields(PromoSignRewardRecord{})
	colsPromoTreasureConfig   = helper.EnumFields(PromoTreasureConfig{})
	colsPromoTreasureRecord   = helper.EnumFields(PromoTreasureRecord{})
	colsMessage               = helper.EnumFields(Message{})
	colsNotice                = helper.EnumFields(TblNotices{})
	colsWithdraw              = helper.EnumFields(tblWithdraw{})
	colsMemberBalance         = helper.EnumFields(TblMemberBalance{})
	colsPayFactory            = helper.EnumFields(TblPayFactory{})
	colsGame                  = helper.EnumFields(Game_t{})
	colsGameItem              = helper.EnumFields(Game_item{})
	colsPlatJson              = helper.EnumFields(platJson{})
	colsPlatform              = helper.EnumFields(Platform{})
	colsFlowConfig            = helper.EnumFields(TblFlowConfig{})
	colsTransType             = helper.EnumFields(TransType{})
	colsTransaction           = helper.EnumFields(MemberTransaction{})
	colsAppUpgrade            = helper.EnumFields(AppUpgrade{})
	colsBonusConfig           = helper.EnumFields(TblBonusConfig{})
	colsReportGame            = helper.EnumFields(tblReportGame{})
	colsReportPlatform        = helper.EnumFields(tblReportPlatform{})
	colsPromoInspection       = helper.EnumFields(TblPromoInspection{})
	colsMemberBankcard        = helper.EnumFields(MemberBankcard{})
	colsBankType              = helper.EnumFields(TblBanktype{})
	colsPromoWeeklyConfig     = helper.EnumFields(TblPromoWeekBetConfig{})
	colsPromoWeekbetRecord    = helper.EnumFields(TblPromoWeekbetRecord{})
	colsMemberAdjust          = helper.EnumFields(TblMemberAdjust{})
	colsRateList              = helper.EnumFields(TblRatelist{})
	colsAgentChannel          = helper.EnumFields(TblOperatorInfo{})
	colsOperatorInfo          = helper.EnumFields(TblOperatorInfo{})
	colsGameConfig            = helper.EnumFields(TblGameConfig{})
	colsProxyInfo             = helper.EnumFields(TblBusinessInfo{})
	colsBusinessInfo          = helper.EnumFields(TblBusinessInfo{})
	colsTurntableInfo         = helper.EnumFields(ryrpc.TblPddTurntableInfo{})
	colsTurntableReview       = helper.EnumFields(ryrpc.TblPddTurntableReview{})
	colsTurntableHistory      = helper.EnumFields(ryrpc.TblPddTurntableHistory{})
)

func zip(a1, a2 []string) []string {

	r := make([]string, 2*len(a1))
	for i, e := range a1 {
		r[i*2] = e
		r[i*2+1] = a2[i]
	}

	return r
}

func CheckLen(str string, min, max int) bool {

	ll := utf8.RuneCountInString(str)
	if ll < min || ll > max {
		return false
	}

	return true
}

func FilterInjection(str string) string {

	array1 := []string{"<", ">", "&", `"`, " ", "/", "=", "?", "`", "\\"}
	array2 := []string{"&lt;", "&gt;", "&amp;", "&quot;", "&nbsp;", "&sol;", "&equals;", "&quest;", "&grave;", "&bsol;"}

	return strings.NewReplacer(zip(array1, array2)...).Replace(str)
}

func Constructor(mt *MetaTable, uri string) {

	meta = mt
	loc, _ = time.LoadLocation("America/Sao_Paulo")

	ryrpc.Constructor(uri)
	err := Lock("admin_load")
	if err == nil {
		BannerFlushCache()
		noticeFlushCache()
		LoadGroups()
		LoadPrivs()
		LoadPlatforms()
		LoadTransTypes()
		GameFlushAll()
		GameConfigLoad()
	}
}

func MurmurHash(str string, seed uint32) uint64 {

	h64 := murmur3.New64WithSeed(seed)
	h64.Write([]byte(str))
	v := h64.Sum64()
	h64.Reset()

	return v
}

func pwdMurmurHash(str string, seed uint32) uint64 {

	s := fmt.Sprintf("%s%d", str, seed)

	v := xxhash3.HashString(s)
	return v
}

type zinc_t struct {
	ID       string `json:"id"`
	Content  string `json:"content"`
	Flags    string `json:"flags"`
	Filename string `json:"filename"`
	Index    string `json:"_index"`
}

//func pushLog(err error, code string) error {
//	fmt.Println(err)
//	helper.InfoLog("系统错误 %s", err)
//	_, file, line, _ := runtime.Caller(1)
//	paths := strings.Split(file, "/")
//	l := len(paths)
//	if l > 2 {
//		file = paths[l-2] + "/" + paths[l-1]
//	}
//	path := fmt.Sprintf("%s:%d", file, line)
//	id := helper.GenId()
//	ts := time.Now()
//	data := zinc_t{
//		ID:       id,
//		Content:  tracerr.SprintSource(err, 2, 2),
//		Flags:    code,
//		Filename: path,
//		Index:    fmt.Sprintf("%s_%04d%02d", meta.Program, ts.Year(), ts.Month()),
//	}
//
//	b, err := helper.JsonMarshal(data)
//	if err != nil {
//		fmt.Println("pushLog MarshalBinary err =  ", err.Error())
//		return err
//	}
//
//	_, err = meta.MerchantBean.Put("zinc_fluent_log", b, 0, 0, 0)
//	if err != nil {
//		fmt.Println("pushLog MerchantBean Put err =  ", err.Error())
//		return err
//	}
//
//	return fmt.Errorf("系统错误 %s", id)
//}

func IpLocation(ipStr string) (string, string, string, error) {

	results, err := meta.IpDB.Get_all(ipStr)
	if err != nil {
		return "", "", "", err
	}

	return results.Country_long, results.Region, results.City, nil
}

func Close() {

	//meta.MerchantBean.Conn.Release()
	meta.MasterDB.Close()
	meta.SlaveDB.Close()
	meta.MerchantRedis.Close()
}

func pushLog(err error, code string) error {
	helper.InfoLog("%s---%s", err.Error(), code)
	return fmt.Errorf("系统错误 %s 错误代码:%s", err.Error(), code)
}
